﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace HitachiLib.Utils
{
    public class DateUtils
    {
        public const int HalfMonth = 1;
        public const int ThreeMonth = 2;
        public const int HalfYear = 3;
        public const int WholeYear = 4;

        public const int TimeMorning = 6;
        public const int TimeAfternoon = 12;
        public const int TimeEvening = 18;

        public static DateTime start_date = DateUtils.PrevDayOfWeek(DateTime.Today, DayOfWeek.Monday);

        public static DateTime PrevDayOfWeek(DateTime dt, DayOfWeek dow)
        {
            while (dt.DayOfWeek != dow) dt = dt.AddDays(-1);
            return dt;
        }

        public static DateTime NextDate(DateTime dt, DayOfWeek dow)
        {
            while (dt.DayOfWeek != dow) dt = dt.AddDays(1);
            return dt;
        }

        public static int GetDate(DateTime dt)
        {
            return dt.Year * 10000 + dt.Month * 100 + dt.Day;
        }

        public static DateTime GetDate(int dt)
        {
            int year = dt / 10000;
            dt = dt - year * 10000;
            int month = dt / 100;
            dt = dt - month * 100;
            int day = dt;
            DateTime r = new DateTime(year, month, day);
            return r;
        }

        public static DateTime GetDate(int dt, int time)
        {
            DateTime r = GetDate(dt);
            r = r.AddHours(time);
            return r;
        }

        private static DateTime AddUnitTime(DateTime dt, int unit)
        {
            switch (unit)
            {
                case WholeYear:
                    return dt.AddYears(1);
                case HalfYear:
                    return dt.AddMonths(6);
                case ThreeMonth:
                    return dt.AddMonths(3);
                case HalfMonth:
                    return dt.AddDays(14);
                default:
                    return dt;
            }
        }
        private static DateTime SubUnitTime(DateTime dt, int unit)
        {
            switch (unit)
            {
                case WholeYear:
                    return dt.AddYears(-1);
                case HalfYear:
                    return dt.AddMonths(-6);
                case ThreeMonth:
                    return dt.AddMonths(-3);
                case HalfMonth:
                    return dt.AddDays(-14);
                default:
                    return dt;
            }
        }
        public static DateTime GetNearest(DateTime stub, int unit)
        {
            DateTime r = stub;
            double fromnow = 0;
            TimeSpan fromnow_ts;
            do
            {
                r = AddUnitTime(r, unit);
                fromnow_ts = r.Subtract(DateTime.Today);
                fromnow = fromnow_ts.TotalDays;
            } while (fromnow < 0);
            while (fromnow >= unit)
            {
                r = SubUnitTime(r, unit);
                fromnow_ts = r.Subtract(DateTime.Today);
                fromnow = fromnow_ts.TotalDays;
            }
            DateTime after = r;
            DateTime before = SubUnitTime(r, unit);
            double dafter = after.Subtract(DateTime.Today).TotalDays;
            double dbefore = DateTime.Today.Subtract(before).TotalDays;
            if (dafter < dbefore)
                return after;
            else
                return before;
        }

        public static DateTime GetNextKnotTime(DateTime stub, int unit)
        {
            DateTime r = stub;
            double fromnow = 0;
            TimeSpan fromnow_ts;
            do
            {
                r = AddUnitTime(r, unit);
                fromnow_ts = r.Subtract(DateTime.Today);
                fromnow = fromnow_ts.TotalDays;
            } while (fromnow < 0);
            while (fromnow >= unit)
            {
                r = SubUnitTime(r, unit);
                fromnow_ts = r.Subtract(DateTime.Today);
                fromnow = fromnow_ts.TotalDays;
            }
            return AddUnitTime(r, unit);
        }
        public static DateTime GetPrevKnotTime(DateTime stub, int unit)
        {
            DateTime r = stub;
            double fromnow = 0;
            TimeSpan fromnow_ts;
            do
            {
                r = AddUnitTime(r, unit);
                fromnow_ts = r.Subtract(DateTime.Today);
                fromnow = fromnow_ts.TotalDays;
            } while (fromnow < 0);
            while (fromnow >= unit)
            {
                r = SubUnitTime(r, unit);
                fromnow_ts = r.Subtract(DateTime.Today);
                fromnow = fromnow_ts.TotalDays;
            }
            return r;
        }

        public static DateTime BaseServiceDate()
        {
            return new DateTime(2011, 5, 2);
        }

        public static int GetDateSigniture(DateTime dt)
        {
            TimeSpan ts = dt.Subtract(BaseServiceDate());
            int d = (int)ts.TotalDays;
            int w = d / 7;
            w = w % 2;
            d = dt.DayOfWeek - DayOfWeek.Sunday;
            int t = dt.Hour;
            return w * 10000 + d * 100 + t;
        }
    }
}
